Redis 集群介绍
Redis 集群是一个提供在多个 Redis 节点间共享数据的程序集。
Redis 集群通过分区来提高程序的可用性,在实际环境中当某个节点宕机或者无法访问的情况下继续处理命令。
Redis 集群的优势(相比单台 Redis 服务):
- 自动分割数据到不同的节点上。
- 整个集群的部分节点失败或者不可访问的情况下能够继续处理命令,提高程序的可用性。
Redis 集群的数据分片
Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念。
Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽。集群的每个节点各负责一部分哈希槽。
例如,当前集群有 3 个节点,则:
- 节点 A 包含 0 到 5500 号哈希槽
- 节点 B 包含 5501 到 11000 号哈希槽
- 节点 C 包含 11001 到 16384 号哈希槽
这种结构很容易添加或者删除节点。比如要新添加一个节点 D ,则需要从节点 A、B、C 中移动部分哈希槽到 D 上。如果要移除节点 A ,则需要将 A 中的哈希槽移动到 B 和 C 节点上,然后将没有任何哈希槽的 A 节点从集群中移除。
由于从一个节点移动哈希槽到另一个节点并不会停止服务,所以无论添加、删除或者改变某个节点哈希槽的数量都不会造成集群不可用的状态。
Redis 集群的主从复制模型
为了使在部分节点宕机或者大部分节点无法提供服务的情况下,集群仍然可用,因此集群使用了主从复制模型,即,每个节点都会有 N-1 个复制从节点。
在上述示例中,具有 A、B、C 三个节点的集群,在没有复制模型的情况下,如果节点 B 宕机,那么整个集群会因为缺少 5501-11000 这个范围内的哈希槽而不可用。
然而,如果在集群创建的时候(或者是创建后,节点发生故障前),为每个节点添加一个从节点 A1、B1、C1,那么整个集群中就有 3 个 master 节点和 3 个 slave 节点组成。这样在节点 B 宕机后,集群便会选举 B1 为新的主节点继续服务,保证整个集群稳健的对外提供服务。
当然,如果 B 和 B1 都宕机后,集群也是不可用的。所以,实质上单单主从复制模型而言,也是降低集群发生故障造成集群不可用的概率。
Redis 数据一致性
Redis 并不能保证数据的强一致性。这意味着在实际中,集群在特定条件下可能会丢失写操作。主要由以下两个原因造成。
第一个原因是因为集群使用了异步复制。集群的“写”操作流程为:
- 客户端向主节点 A 写入一条命令;
- 主节点 A 向客户端回复命令执行结果;
- 主节点将“写”操作复制给它的从节点 A1、A2 等。
之所以使用异步复制,是因为同步复制会大大降低主节点处理命令的速度。这也是在性能和数据一致性之间做出权衡。
另一个原因则是在集群中会出现网络分区。当出现网络分区,并且一个客户端与至少一个主节点在内的少数实例被孤立,就会出现数据不一致的情况。
举个栗子,假设一个集群包含 A、B、C、A1、B1、C1 六个节点,其中 A、B、C 为主节点,A1、B1、C1 为 A、B、C 的从节点。同时,有一个客户端 Z1,此时出现网络分区,集群分为两方,大的一方包含节点 A、C、A1、B1、C1,小的一方包含节点 B 和客户端 Z1。
此时,Z1 仍然能够向主节点 B 写入数据,但当网络分区时间较长,致使大的一方将 B1 选举为新的maser,那么 Z1 写入 B 中的数据便丢失了。
需要注意的是,在网络分区期间,客户端 Z1 向主节点 B 发送写命令的最大时间是有限制的,这一时间限制称为节点超时时间(node timeout),是 Redis 集群的一个重要配置项。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。